/**
 * Created by qunxing.du on 2016/7/28.
 * Copyright 2016 汉威.智慧环保事业部 Limited.
 * All rights reserved.
 */
package com.hw.one.collect.zzcity.handler;

import com.hw.one.collect.data.DataService;
import com.hw.one.collect.model.DataServiceType;
import com.hw.one.collect.util.ConvertUtil;
import com.mongodb.BasicDBList;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 纵转换数据处理器
 */
@Component
public class TransformDataHandler extends DataService implements IHandler {
    private static Logger log = Logger.getLogger(TransformDataHandler.class);

    @Resource
    protected MongoTemplate mongoTemplate;
    @Resource
    private MongoTemplate mongoTemplateDev;

    private static final String FACOTRS = "100=SO2,101=NO2,102=O3,103=CO,104=PM10,105=PM25,106=NOx,107=NO," +
            "108=WS,109=WD,110=ATMO,111=TEMP,112=HUM";
    private static Map<String, String> allFactors;
    private static final String PADDING_VAL = null;//填充值


    /**
     * 处理方法
     *
     * @param o
     * @param handlerChain
     * @return
     * @throws Exception
     */
    @Override
    public synchronized Object handle(Object o, String name, HandlerChain handlerChain) throws Exception {
        BasicDBList list = transformData(o);

        log.info("待保存转换后数据:" + name + TRANSFORM_COLLETCION_SUFFIX + "," + list.size());
        if(!name.equals(DataServiceType.RAW_ONEHOUR.name()) && !name.equals(DataServiceType.AUDIT_ONEHOUR.name())
                && !name.equals(DataServiceType.RAW_FIVEMIN.name()) && !name.equals(DataServiceType.AUDIT_FIVEMIN.name())){
            //插入正式库
            insertProductData(list, name +TRANSFORM_COLLETCION_SUFFIX);
            //插入开发库备份
//            insertDevData(list, name + TRANSFORM_COLLETCION_SUFFIX);
        }
        return handlerChain.handle(list.copy(), name, handlerChain);
    }

    /**
     * 转换数据
     *
     * @param data
     * @return
     */
    private BasicDBList transformData(Object data) throws Exception{
        //json字符串转成list集合
        List<Map> list = ConvertUtil.toList(data);
        //list集合解析
        List<Map> parsedList = parseList(list);
        //转成basicDBList
        return getBasicDBList(parsedList);
    }

    /**
     * list集合中实体纵转横
     *
     * @param list
     * @return
     */
    private List<Map> parseList(List<Map> list) throws Exception {
        List<Map> results = new ArrayList<>();
        for (Map map : list) {
            saveOrUpdate(results, map);
        }
        //填充空数据
        paddingData(results);
        return results;
    }

    /**
     * 填充空数据
     *
     * @param list
     */
    private void paddingData(List<Map> list) {
        for (Map map : list) {
            Iterator<String> its = allFactors.values().iterator();
            while (its.hasNext()) {
                String key = its.next();
                if (!map.containsKey(key)) {
                    map.put(key, PADDING_VAL);
                }
            }
        }
    }

    /**
     * 添加或修改
     *
     * @param list
     * @param map
     */
    private void saveOrUpdate(List<Map> list, Map map) throws Exception {
        String timePoint = (String) map.get("TimePoint");
        String uCode = (String) map.get("UCode");
        boolean isExist = false;
        for (Map result : list) {
            if (result.containsValue(timePoint.replace("T", " ")) && result.containsValue(uCode)) {
                //存在即修改
                modifyResult(result, map);
                isExist = true;
                break;
            }
        }
        //不存在即添加
        if (!isExist) {
            saveResult(list, map);
        }
    }

    /**
     * 修改结果集
     *
     * @param result
     * @param map
     * @return
     */
    private boolean modifyResult(Map result, Map map) throws Exception {
        String pCode = (String) map.get("PCode");
        Double monvalue = ConvertUtil.toDouble (map.get("Monvalue"));
        result.put(getFactors().get(pCode), monvalue);
        return true;
    }

    /**
     * 不存在即添加
     *
     * @param list
     * @param map
     * @return
     */
    private boolean saveResult(List list, Map map) throws Exception{
        String timePoint = (String) map.get("TimePoint");
        String uCode = (String) map.get("UCode");
        String pCode = (String) map.get("PCode");
        Double monvalue = ConvertUtil.toDouble (map.get("Monvalue"));
        log.info("添加数据："+timePoint+"|"+uCode+"|"+pCode+"|"+monvalue);
        Map newMap = new HashMap();
        newMap.put("recTime", timePoint.replace("T", " "));
        newMap.put("UCode", uCode);
        newMap.put(getFactors().get(pCode), monvalue);
        list.add(newMap);
        return true;
    }

    /**
     * 获取因子键值集合
     *
     * @return
     */
    private Map<String, String> getFactors() {
        if (allFactors == null) {
            allFactors = super.getFactors(FACOTRS);
        }
        return allFactors;
    }

    /**
     * 插入生产数据
     *
     * @param basicDBList
     * @param name
     */
    private void insertProductData(BasicDBList basicDBList, String name) {
        log.info("插入转换数据到生产库");
        mongoTemplate.insert(basicDBList, name);
    }

    /**
     * 插入数据到开发库
     *
     * @param basicDBList
     * @param name
     */
    private void insertDevData(final BasicDBList basicDBList, final String name) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("插入转换数据到开发库");
                mongoTemplateDev.insert(basicDBList, name);
            }
        }).start();
    }
}
